<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Promotion\Ctl;

use Srv\Apps\Apis\Skit\Ctl\SkitInfoCtl;
use Srv\Apps\Apis\Skit\Ctl\SkitSeriesCtl;
use Srv\Apps\Proto\DTO\Promotion\WappLinkAddDTO;
use Srv\Apps\Proto\DTO\Promotion\WappLinkEditDTO;
use Srv\Apps\Proto\DTO\Promotion\WappLinkListDTO;
use Srv\Apps\Proto\Enum\WappProxyTypeEnum;
use Srv\Apps\Proto\VO\Promotion\WappLinkListVO;
use Srv\Apps\Proto\VO\Promotion\WappLinkVO;
use Srv\Apps\Proto\VO\Skit\SkitInfoVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommString;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;

final class WappLinkCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write
    private string $wappLinkUrl             = 'https://wwwxc.nilela.com/apppromo/{KEY}/{PIXEL_ID}';     // Web2App地址



    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        if($thisObject->isRelease()){
            $thisObject->wappLinkUrl        = "https://www.xc.com/apppromo/{KEY}/{PIXEL_ID}";
        }
        return $thisObject;
    }

    /**
     * @param int $walrId
     * @return array
     * getWappLinkSrc
     */
    public function getWappLinkSrc(int $walrId):array
    {
        if($walrId < 1) return [];
        $isFail     = false;
        $info       = $this->DbAuto->getDataOne('SELECT walr_id, walr_key, walr_name, skio_id, walr_pixel_id, walr_pixel_id_token, walr_adid, walr_ad_pos_id, walr_proxy_type, walr_app_type, walr_create_time, walr_update_time FROM '.$this->DbAuto->getTableNameAll('wapp_link_record').' WHERE walr_id='.$walrId.' AND walr_delete=0', $isFail);
        if($isFail || !isset($info['walr_id'])) return [];
        return $info;
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return WappLinkListVO|null
     * getWappLinkList
     */
    public function getWappLinkList(Page $Page, array $whereData): ?WappLinkListVO
    {
        $limitString            = $Page->getLimitString();
        $whereString            = ' WHERE walr_delete=0 ';
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case WappLinkListDTO::_walrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_id='. intval($val);
                    break;
                case WappLinkListDTO::_name:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_name LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case WappLinkListDTO::_key:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_key LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case WappLinkListDTO::_adId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_adid LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case WappLinkListDTO::_proxyType:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_proxy_type='. intval($val);
                    break;
                case WappLinkListDTO::_adPosId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_ad_pos_id LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case WappLinkListDTO::_appType:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'walr_app_type LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
            }
        }
        $isFail                 = false;
        $sql                    = 'SELECT SQL_CALC_FOUND_ROWS walr_id, walr_key, walr_name, skio_id, walr_pixel_id, walr_pixel_id_token, walr_adid, walr_ad_pos_id, walr_proxy_type, walr_app_type, walr_create_time, walr_update_time FROM '.$this->DbAuto->getTableNameAll('wapp_link_record').$whereString.' ORDER BY walr_id DESC '.$limitString;
        $list                   = $this->DbAuto->getData($sql, $isFail);
        $totalNum               = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $WappLinkVOList         = [];
        if(CommArray::isForeach($list)){
            $skioIdList         = array_map('intval', array_unique(array_column($list, 'skio_id')));
            $SkitInfoVOList     = SkitInfoCtl::tag()->getSkitInfoBatch($skioIdList);
            foreach($list as $info){
                $walrIdItem         = intval($info['walr_id']??0);
                if($walrIdItem < 1) continue;
                $WappLinkVO         = $this->getWappLinkVO($info);
                if(!($WappLinkVO instanceof WappLinkVO)) continue;
                $skioIdItem         = intval($info['skio_id']);
                $SkitInfoVO         = $SkitInfoVOList[$skioIdItem]??null;
                if($SkitInfoVO instanceof SkitInfoVO) {
                    $WappLinkVO->setSkitInfo($SkitInfoVO);
                }
                $WappLinkVOList[]   = $WappLinkVO;
            }
        }
        $WappLinkListVO         = new WappLinkListVO();
        $WappLinkListVO->setList($WappLinkVOList);
        $WappLinkListVO->setPage($Page->getPageVO($totalNum));
        return $WappLinkListVO;
    }

    /**
     * @param int $walrId
     * @return WappLinkVO|null
     * getWappLinkInfo
     */
    public function getWappLinkInfo(int $walrId):?WappLinkVO
    {
        $infoSrc    = $this->getWappLinkSrc($walrId);
        if(!isset($infoSrc['walr_id'])) return null;
        return $this->getWappLinkVO($infoSrc);
    }

    /**
     * @param array $info
     * @return WappLinkVO|null
     * getWappLinkVO
     */
    public function getWappLinkVO(array $info):?WappLinkVO
    {
        $walrId             = intval($info['walr_id']??0);
        if($walrId < 1) return null;
        $WappLinkVO         = new WappLinkVO();
        $WappLinkVO->setWalrId($walrId);
        $WappLinkVO->setName(trim($info['walr_name']));
        $WappLinkVO->setKey(trim($info['walr_key']));
        $WappLinkVO->setSkioId(intval($info['skio_id']));
        $WappLinkVO->setPixelId(trim($info['walr_pixel_id']));
        $WappLinkVO->setPixelIdToken(trim($info['walr_pixel_id_token']));
        $WappLinkVO->setAdId(trim($info['walr_adid']));
        $WappLinkVO->setAdPosId(trim($info['walr_ad_pos_id']));
        $WappLinkVO->setAppType(trim($info['walr_app_type']));
        $WappLinkVO->setProxyType(WappProxyTypeEnum::parseValue($info['walr_proxy_type']));
        $WappLinkVO->setCreateTime(intval($info['walr_create_time']));
        $WappLinkVO->setUpdateTime(intval($info['walr_update_time']));
        $url                = str_replace('{KEY}', $WappLinkVO->getKey(), $this->wappLinkUrl);
        $url                = str_replace('{PIXEL_ID}', $WappLinkVO->getPixelId(), $url);
        if(strlen($WappLinkVO->getAppType()) > 0) $url .= '/'.$WappLinkVO->getAppType();
        $WappLinkVO->setUrl($url);
        return $WappLinkVO;
    }

    /**
     * @param array $setData
     * @return int
     * wappLinkAdd
     */
    public function wappLinkAdd(array $setData):int
    {
        if(count($setData) < 1) return 0;
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case WappLinkAddDTO::_name:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_name=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkAddDTO::_skioId:
                    $skioId         = intval($val);
                    $skitInfoSrc    = SkitInfoCtl::tag()->getSkitInfoSrc($skioId);
                    if(!isset($skitInfoSrc['skio_id'])) return 0;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skio_id='.$skioId;
                    break;
                case WappLinkAddDTO::_pixelId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_pixel_id=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkAddDTO::_pixelIdToken:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_pixel_id_token=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkAddDTO::_adId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_adid=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkAddDTO::_proxyType:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_proxy_type='.intval($val);
                    break;
                case WappLinkAddDTO::_adPosId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_ad_pos_id=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkAddDTO::_appType:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_app_type=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
            }
        }
        if(strlen($setString) < 1)  return 0;
        $currTime   = CommTime::getTimeStamp(0);
        $randKey    = $this->getWappLinkKey();
        $isFail     = false;
        $sql        = 'INSERT INTO '.$this->DbAuto->getTableNameAll('wapp_link_record').' SET '.$setString.', walr_key=\''.$this->DbAuto->getRealEscapeString($randKey).'\', walr_delete=0, walr_create_time='.$currTime.', walr_update_time='.$currTime;
        $walrId     = $this->DbAuto->getDataId($sql, $isFail);
        if($isFail || $walrId < 1) return 0;
        return $walrId;
    }

    /**
     * @param int $walrId
     * @param array $setData
     * @return bool
     * wappLinkEdit
     */
    public function wappLinkEdit(int $walrId, array $setData):bool
    {
        if($walrId < 1 || count($setData) < 1) return false;
        $setString      = '';
        foreach ($setData as $key => $val){
            switch ($key){
                case WappLinkEditDTO::_name:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_name=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkEditDTO::_proxyType:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_proxy_type='. intval($val);
                    break;
                case WappLinkEditDTO::_pixelId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_pixel_id=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkEditDTO::_pixelIdToken:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_pixel_id_token=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkEditDTO::_adId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_adid=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkEditDTO::_skioId:
                    $skioId         = intval($val);
                    $skitInfoSrc    = SkitInfoCtl::tag()->getSkitInfoSrc($skioId);
                    if(!isset($skitInfoSrc['skio_id'])) return false;
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'skio_id='.$skioId;
                    break;
                case WappLinkEditDTO::_adPosId:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_ad_pos_id=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
                case WappLinkEditDTO::_appType:
                    $setString      .= (strlen($setString) > 0 ? ', ' : '') . 'walr_app_type=\''.$this->DbAuto->getRealEscapeString($val).'\'';
                    break;
            }
        }
        if(strlen($setString) < 1) return false;
        $isFail     = false;
        $currTime   = CommTime::getTimeStamp(0);
        $sql        = 'UPDATE '.$this->DbAuto->getTableNameAll('wapp_link_record').' SET '.$setString.', walr_update_time='.$currTime.' WHERE walr_id='.$walrId.' AND walr_delete=0';
        if($this->DbAuto->getDataNum($sql, $isFail) < 1 || $isFail) return false;
        return true;
    }

    /**
     * @return string
     * getWappLinkKey
     */
    public function getWappLinkKey():string
    {
        $minLength          = 8;        // 最小长度
        $maxLength          = 16;       // 最大长度
        $maxNum             = 200;
        $currNum            = 1;
        $indexNum           = 1;
        $randKey            = strtolower(CommString::genRandStr($minLength));
        while($currNum <= $maxNum){
            $idFind         = $this->DbAuto->getDataInt('SELECT walr_id FROM '.$this->DbAuto->getTableNameAll('wapp_link_record').' WHERE binary walr_key=\''.$this->DbAuto->getRealEscapeString($randKey).'\'', 'walr_id');
            if($idFind < 1) break;
            if($indexNum >= 50){                // 失败自增长度1
                $indexNum   = 0;
                $minLength  += 1;
            }
            if($minLength > $maxLength) break;  // 长度封顶
            $randKey        = strtolower(CommString::genRandStr($minLength));
            ++$indexNum;
            ++$currNum;
        }
        return $randKey;
    }
}